package bat.iog.hytool.reactor.multiple;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * 单Reactor多线程模型
 */
public class Reactor implements Runnable{

    private ServerSocketChannel serverSocketChannel = null;
    
    private Selector selector = null;

    /**
     * 绑定端口
     */
    public Reactor(){
        try {
            selector = Selector.open();
            serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.configureBlocking(false);
            serverSocketChannel.socket().bind(new InetSocketAddress(9999));
            SelectionKey selectionKey = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            selectionKey.attach(new Acceptor());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    //进行分发任务
    public void dispatch(Runnable runnable) {
        if (runnable != null) {
            runnable.run();
        }
    }
    
    @Override
    public void run() {
        while (true) {
            try {
                //selector.select()会一直阻塞到有一个通道在你注册的事件上就绪了
                selector.select();
                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()) {
                    SelectionKey selectionKey = iterator.next();
                    
                    dispatch((Runnable) selectionKey.attachment());
                    iterator.remove();
                }
                
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    class Acceptor implements Runnable {
        public void run() {
            try {
                SocketChannel socketChannel = serverSocketChannel.accept();
                if (socketChannel != null) {
                    System.out.println("接收到来自客户端（" + socketChannel.socket().getInetAddress().getHostAddress() + "）的连接");
                    //new Handler(selector, socketChannel);
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
